package org.funtester.performance.books.chapter01.section4;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义线程池拒绝策略示例
 */
public class RejectDemo {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(Thread.currentThread().getName() + "  " + System.currentTimeMillis() + "  任务被拒绝,线程池已满");// 打印任务被拒绝信息
                try {
                    Thread.sleep(1000);// 等待1秒,避免递归调用导致栈溢出
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                executor.execute(r);
            }
        });// 自定义线程池
        AtomicInteger index = new AtomicInteger();// 索引,用于标识任务
        for (int i = 0; i < 3; i++) {
            int sequence = i;// 任务序号,用于标识任务,由于lambda表达式中的变量必须是final或者等效的,所以这里使用局部变量
            try {
                executor.execute(() -> {// 提交任务
                    try {
                        Thread.sleep(1000);// 模拟任务执行,睡眠1秒,避免任务过快执行完毕
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(Thread.currentThread().getName() + "  " + System.currentTimeMillis() + "  任务" + sequence + "执行完成");// 打印任务执行完成信息
                });
                System.out.println(Thread.currentThread().getName() + "  " + System.currentTimeMillis() + "  任务" + sequence + "提交成功");// 打印任务提交成功信息
            } catch (Exception e) {
                System.out.println(Thread.currentThread().getName() + "  " + System.currentTimeMillis() + "  任务" + sequence + "被拒绝,异常信息:" + e.getMessage());// 打印任务被拒绝信息
            }
        }
        executor.shutdown();// 关闭线程池,不再接受新任务,但会执行完队列中的任务,并不会立即关闭
    }

}
